﻿Imports Microsoft.DirectX.Direct3D
Imports Microsoft.DirectX
Imports Commander_Wars.Spieletools
Public Class ObjektSpieler
    Implements ICloneable

    Enum Gebaeudesuche
        Sendetuerme
        Fonds
        Minen
    End Enum

    Public Const MaximaleDeffensivestaerke As Integer = 190
    Public Const TextWarteZeit As Integer = 20
#Region "AI"
    ''' <summary>
    ''' Here is the Main AI Class saved for this player
    ''' </summary>
    ''' <remarks></remarks>
    Public AI_Class As ObjektKI = Nothing
#End Region

#Region "Variablen"
    ''' <summary>
    ''' Wenn False greift die KI keine Schweissnaehte, Mauern an, aber weiterhin feindliche Minigeschuetze usw.
    ''' Hat nur fuer KI-Stufen Normal aufwaerts auswirkungen.
    ''' </summary>
    ''' <remarks></remarks>
    Public NeutraleGebaeudeAngriff As Boolean = True
    Private FfondsproStadt As Integer
    Public Property FondsproStadt() As Integer
        Get
            Return FfondsproStadt
        End Get
        Set(ByVal value As Integer)
            FfondsproStadt = value
        End Set
    End Property
    Public KOS() As ObjektKO
    Private Fond As Integer
    Public Property Fonds() As Integer
        Get
            Return Fond
        End Get
        Set(ByVal value As Integer)
            If value > 0 Then
                Fond += FondsproStadt * value
            ElseIf value = 0 Then
                Fond = 0
            Else
                Fond += value
            End If
        End Set
    End Property
    Public Sub AddFonds(ByVal Value As Integer)
        Fond += Value
        If Fond < 0 Then
            Fond = 0
        End If
    End Sub
    Public Sub SetFonds(ByVal neuFonds As Integer)
        Fond = neuFonds
    End Sub
    Private Teams As Char
    Public Property Team() As Char
        Get
            Return Teams
        End Get
        Set(ByVal value As Char)
            Teams = value
        End Set
    End Property
    Private Armeen As String
    Public Property Armee() As String
        Get
            Return Armeen
        End Get
        Set(ByVal value As String)
            Armeen = value
        End Set
    End Property
    Private Spielern As Integer
    Public Property Spieler() As Integer
        Get
            Return Spielern
        End Get
        Set(ByVal value As Integer)
            Spielern = value
        End Set
    End Property
    Private Gabeleisten As Boolean = True
    ''' <summary>
    ''' Gibt an ob dieser Spieler seine Gabe einsetzen kann.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Gabeleiste() As Boolean
        Get
            Return Gabeleisten
        End Get
        Set(ByVal value As Boolean)
            Gabeleisten = value
        End Set
    End Property
    Public KIStufe As KIStufen = KIStufen.Mensch
    Enum KIStufen
        Mensch
        Kinderleicht
        Einfach
        Normal
        Mittel
        Schwer

        Geschlossen
        Offen
        Passiv
    End Enum

    Public Function GetGebaeude(ByVal Suche As Gebaeudesuche)
        Dim Anzahl As Integer = 0
        Dim AnzahlSchlachten As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then AnzahlSchlachten = 1
        For I = 0 To AnzahlSchlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If G IsNot Nothing Then
                            If G.Spieler = Me.Spieler Then
                                Select Case Suche
                                    Case Gebaeudesuche.Sendetuerme
                                        If G.Angriff = ObjektGebaeude.Angriffe.Sendeturm Then
                                            Anzahl += 1
                                        End If
                                    Case Gebaeudesuche.Minen
                                        If G.Angriff = ObjektGebaeude.Angriffe.Mine Then
                                            Anzahl += 1
                                        End If
                                    Case Gebaeudesuche.Fonds
                                        If G.getFonds Then
                                            Anzahl += 1
                                        End If
                                End Select
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Anzahl
    End Function
    '<NonSerialized()> Public Sendetuerme As Integer = 0
    '<NonSerialized()> Public Minen As Integer = 0
    '    Public Geldgebaeude As Integer = 0
    Private Bauliste As Bauliste = Nothing
    Public Function GetBauliste() As Bauliste
        If Bauliste Is Nothing Then
            Bauliste = New Bauliste(ObjektLadeklasse.GetBauliste(Baulisten.None))
        End If
        If Objektverwalter.Spielfeld IsNot Nothing Then
            If Objektverwalter.Spielfeld.Regeln.MaxTroops > 0 Then
                If CountUnits() < Objektverwalter.Spielfeld.Regeln.MaxTroops Then
                    Return Bauliste
                Else
                    Return New Bauliste(ObjektLadeklasse.GetBauliste(Baulisten.None))
                End If
            Else
                Return Bauliste
            End If
        Else
            Return Bauliste
        End If
    End Function
    Public Sub SetBauliste(ByVal Bauliste As Bauliste)
        Me.Bauliste = Bauliste
    End Sub
    Private Fabrikfondse As Integer
    ''' <summary>
    ''' Am Punkt X Y Z=Schlacht sieht man W Felder alles auch in Waelder und Riffe
    ''' </summary>
    ''' <remarks></remarks>
    Public Sichtfelder As Vector4() = {}
    Public Property Fabrikfonds() As Integer
        Get
            Return Fabrikfondse
        End Get
        Set(ByVal value As Integer)
            Fabrikfondse = value
        End Set
    End Property
    Public VeraenderteWerte As WertedurchGabegeaendert
    Public Bauprioritaeten As KIGenerellerSuperBau.PrioritaetsBau = Nothing
    Public SpielerBaublockade As Baublockade = Nothing

    Public Spielername As String = "No Name"
#Region "Texturen"
    Public ExternGezogeneEinheiten As ExternGezogeneEinheit() = {}
    Public Farbe As Color
    Structure SpezialGebaeude
        Implements ICloneable
        Public Sub New(ByVal neuTextur As String, ByVal neuID As String, ByVal Farbtabelle As Bitmap, Optional ByVal Neutral As Boolean = False)

        End Sub
        Private Textur As Texture
        Public ReadOnly Property SpezialgebaeudeTextur() As Texture
            Get
                Return Textur
            End Get
        End Property
        Private SymbolTextur As Texture
        Public ReadOnly Property SpezialgebaeudeSymbol() As Texture
            Get
                Return SymbolTextur
            End Get
        End Property
        Private ID As String
        Public ReadOnly Property GebaeudeID() As String
            Get
                Return ID
            End Get
        End Property
        ''' <summary>
        ''' Nur eine flache Kopie
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Clone() As Object Implements System.ICloneable.Clone
            Return MemberwiseClone()
        End Function
    End Structure

    Structure ExternGezogeneEinheit
        Implements ICloneable
        Const Version As Byte = 0
        Dim ZielX As Integer
        Dim ZielY As Integer
        Dim Einheit As ObjektEinheit
        Dim Befehl As Befehle
        ''' <summary>
        ''' Z.Bsp. GebaeudeID das gebaut werden soll.
        ''' </summary>
        ''' <remarks></remarks>
        Dim ZielID As String
        Dim NaechsterBefehl As NaechsteBefehle
        Enum Befehle
            WartenBisAngriff
            Bauen
            Heilen
        End Enum
        Enum NaechsteBefehle
            Keiner
            Entfernen
        End Enum
        Public Sub New(ByVal ZielX As Integer, ByVal ZielY As Integer, ByVal Einheit As ObjektEinheit, ByVal Befehl As Befehle, ByVal ZielID As String, ByVal NaechsterBEfehl As NaechsteBefehle)
            Me.ZielX = ZielX
            Me.ZielY = ZielY
            Me.ZielID = ZielID
            Me.NaechsterBefehl = NaechsterBEfehl
            Me.Befehl = Befehl
            Me.Einheit = Einheit
        End Sub
        ''' <summary>
        ''' Eine Flache Kopie nicht gut.
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Clone() As Object Implements System.ICloneable.Clone
            Return MemberwiseClone()
        End Function

        Public Sub Write(ByRef StrW As Filestream)
            StrW.WriteByte(Version)
            Dim B(3) As Byte
            B = IntToBytes(ZielX)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(ZielY)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(Einheit.X)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(Einheit.Y)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(Einheit.GetMap)
            StrW.WriteByte(Befehl)
            StrW.WriteByte(NaechsterBefehl)
            WriteString(StrW, ZielID)
        End Sub
        Public Sub Read(ByRef StrR As Filestream)
            Dim V As Byte = StrR.ReadByte
            Dim B(3) As Byte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            ZielX = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            ZielY = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            Dim X As Integer = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte
            Next
            Dim Y As Integer = BytesToInt(B)
            Dim Schlacht As Integer = StrR.ReadByte
            Einheit = New EinheitAmphibienpanzer(Schlacht, X, Y)
            Befehl = StrR.ReadByte
            NaechsterBefehl = StrR.ReadByte
            ZielID = ReadString(StrR)
        End Sub
    End Structure
#End Region
#End Region

#Region "Spieler erstellen"
    Public Sub New(ByVal neuSpieler As Integer, ByVal Farbe As Color, ByVal neuFondsproStadt As Integer, ByVal neuKOS() As ObjektKO, ByVal Startfonds As Integer, ByVal neuArmee As String, ByVal neuTeam As Char, ByVal neuBauliste As ObjektTabelle, ByVal neuKIStufe As KIStufen, ByVal Fabrikfonds As Integer)
        Spieler = neuSpieler
        Armee = neuArmee
        FondsproStadt = neuFondsproStadt
        KOS = neuKOS
        Fond = Startfonds
        Team = neuTeam
        Me.Farbe = Farbe
        KIStufe = neuKIStufe
        Bauliste = neuBauliste
        Me.Fabrikfondse = Fabrikfonds
        VeraenderteWerte = New WertedurchGabegeaendert(0)
    End Sub

    Public Function KannGabe() As Boolean
        If VeraenderteWerte.Gabeeinsatz = True Then
            If KOS(0).KannGabe Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    Public Function KannSpezialGabe() As Boolean
        If VeraenderteWerte.Gabeeinsatz = True Then
            If KOS(0).KannSpezialGabe Then
                Return True
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    Public Function KannDoppelGabe() As Boolean
        If VeraenderteWerte.Gabeeinsatz = True Then
            If IsNothing(KOS(1)) = False Then
                If Objektverwalter.Spielfeld.Regeln.DoppelGabe Then
                    If KOS(0).KannSpezialGabe And KOS(1).KannSpezialGabe Then
                        Return True
                    Else
                        Return False
                    End If
                Else
                    Return False
                End If
            Else
                Return False
            End If
        Else
            Return False
        End If
    End Function
    ''' <summary>
    ''' Wechselt die KO's
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Wechsel()
        If DataSettings.KonsolenSpielBefehle Then
            Konsole.Write("Switch CO's.")
        End If
        If Objektverwalter.Spielfeld.AktuellerSpieler.KIStufe <> ObjektSpieler.KIStufen.Passiv Then
            Dim Befehl As New KINetzwerkBefehl
            Befehl.Befehl = ObjektKI.KIModiExtern.Wechsel
            Befehl.KooX = -1
            Befehl.KooY = -1
            Befehl.WegX = New Integer() {-1}
            Befehl.WegY = New Integer() {-1}
            Befehl.OpferX = -1
            Befehl.OpferY = -1
            Befehl.AngreiferSchaden = -1
            Befehl.Verteidigerschaden = -1
            Befehl.Spieler = Objektverwalter.Spielfeld.AktuellerSpieler.Spieler
            Hauptmenue.NetzBefehlSenden(Befehl)
        End If

        Dim Text As String = Objektverwalter.GetKO(KOS(1).Bild).KOBeschreibung.Tauschsaetze(Zufallszahl(0, Objektverwalter.GetKO(KOS(1).Bild).KOBeschreibung.Tauschsaetze.Length - 1))
        ObjektKODialog.NeuerDialog(New ObjektKODialog.KOText() {New ObjektKODialog.KOText(KOS(1).Bild, Text, Spieler, ObjektKOTextZeile.KOGesichtsAusdruck.Lachend, TextWarteZeit)}, , ObjektKODialog.NaechsteAktionen.RundenEnde)
        Dim KO As ObjektKO = KOS(0)
        KOS(0) = KOS(1)
        KOS(1) = KO
        'KO Einheit uebergeben!
        KOS(0).SetKOEinheit(KOS(1).GetKOUnit)

        Grafikengine.Lichtaendern(KOS(0).getLichtfarbe)
    End Sub

    Public Function GetDeffensivStaerke(ByVal Einheit As ObjektEinheit, ByVal Landschaft As ObjektLandschaft, ByVal Fernkampf As Boolean, Optional ByVal IgnoreDeffence As Boolean = False) As Integer
        Dim Deffensive As Integer = 100
        'Wir laden die Deffensiv Staerke der Einheit

        'Standard Deffensive
        If IsNothing(KOS(0).DeffensivStaerke) = False Then
            Deffensive = KOS(0).DeffensivStaerke.GetWert(Einheit.EinheitenID)
            If Deffensive < 0 Then
                Deffensive = 100
            End If
        End If

        Deffensive = (Deffensive - 100) * KOS(0).GetKOZoneBoost(Einheit) + 100
        If Not IgnoreDeffence Then
            'Deckung
            If Not Landschaft Is Nothing Then
                Dim Deckung As Integer = Landschaft.GetDeckung
                If Not Einheit.IsFlyingUnit Then
                    Deffensive += 10 * Deckung * Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).VeraenderteWerte.TerrainVeraender
                End If
            End If
        End If
        Deffensive += GetGebaeude(ObjektSpieler.Gebaeudesuche.Sendetuerme) * KOS(0).SendeTurmStaerke.Y

        If Fernkampf = True Then
            Deffensive += KOS(0).Zusatzdeffensive.Y * KOS(0).GetKOZoneBoost(Einheit)
        Else
            Deffensive += KOS(0).Zusatzdeffensive.X * KOS(0).GetKOZoneBoost(Einheit)
        End If



        'Je nach Stufe wird die Einheit staerker
        Select Case Einheit.EinheitenStufe
            Case ObjektEinheit.Stufe.Leutnant
                Deffensive += 0
            Case ObjektEinheit.Stufe.Offizier
                Deffensive += 0
            Case ObjektEinheit.Stufe.General
                Deffensive += 10
            Case ObjektEinheit.Stufe.Veteran
                Deffensive += 20
            Case ObjektEinheit.Stufe.KO
                Deffensive += 20
            Case Else
                Deffensive += 0
        End Select
        Deffensive += Einheit.ATKDEFBoost.Y
        'Wenn unsere Deffensive zu hoch ist sind wir unzerstoerbar und das wuerde die Spiellaune senken.
        If DataSettings.CommanderWarsGameModus < CommanderWarsGameModi.CommanderWars Then
            If Deffensive > MaximaleDeffensivestaerke Then Deffensive = MaximaleDeffensivestaerke
        End If
        If Deffensive < 0 Then Deffensive = 0

        Return Deffensive
    End Function
    Public Function GetOffensivStaerke(ByVal Einheit As ObjektEinheit, ByVal Landschaft As ObjektLandschaft, ByVal VerteidigerX As Integer, ByVal VerteidigerY As Integer, ByVal AngreiferLeben As Single, ByVal VerteidigerLeben As Single, ByVal CounterAttack As Boolean) As Integer
        Dim Schlacht As Integer = ObjektSpielfeld.Bodenschlacht
        If Einheit.X >= 0 Then
            Schlacht = Einheit.GetMap
        End If
        Dim AngreiferX As Integer = Einheit.X
        Dim AngreiferY As Integer = Einheit.Y
        If AngreiferX >= 0 Then
            If Not Objektverwalter.Spielfeld.Laufen Is Nothing And Objektverwalter.Spielfeld.Einheiten(AngreiferX, AngreiferY, Einheit.GetMap) Is Nothing Then
                AngreiferX = Objektverwalter.Spielfeld.Laufen.Position.X
                AngreiferY = Objektverwalter.Spielfeld.Laufen.Position.Y
            End If
        End If
        Dim Deffender As ObjektEinheit = Nothing
        If VerteidigerX >= 0 Then
            Deffender = Objektverwalter.Spielfeld.Einheiten(VerteidigerX, VerteidigerY, Schlacht)
        End If
        Dim Offensive As Integer = 100


        'Standard Bonus
        If IsNothing(KOS(0).OffensivStaerke) = False Then
            Offensive = KOS(0).OffensivStaerke.GetWert(Einheit.EinheitenID)
            If Offensive < 0 Then
                Offensive = 100
            End If
        End If
        If CounterAttack Then
            If KOS(0).GegenFeuerkraft <> 0 Then
                Offensive += KOS(0).GegenFeuerkraft * 100 - 100
            End If
        End If

        Select Case DataSettings.CommanderWarsGameModus
            Case CommanderWarsGameModi.AdvanceWarsDC
                If Not KOS(0).Wetterimmunitaet.Contains(Objektverwalter.Spielfeld.Regeln.Wetter) Then
                    'Oh Sandsturm ist in DC\ DoR verdammt heftig
                    If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Sandsturm Then
                        Offensive -= 30
                    End If
                End If
            Case CommanderWarsGameModi.CommanderWars2
                If Not KOS(0).Wetterimmunitaet.Contains(Objektverwalter.Spielfeld.Regeln.Wetter) Then
                    'Oh Sandsturm ist in DC\ DoR verdammt heftig
                    If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Sandsturm Then
                        If Einheit.Bewegungsart.ToLower <> "wuestenketten" Then
                            Offensive -= 20
                        End If
                    End If
                End If
        End Select
        'Manche Kos bekommen Noni wenn Einheiten angegriffen werden koennen oder so
        If VerteidigerX >= 0 And VerteidigerY >= 0 Then
            If Not KOS(0).Kampfbonus = ObjektKO.Kampfboni.No Then
                Dim AnzahlderEinheiten As Integer = 0
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, Objektverwalter.Spielfeld.MomentaneSchlacht).Hidden Then
                            If IsNothing(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht)) = False Then
                                Select Case KOS(0).Kampfbonus
                                    Case ObjektKO.Kampfboni.Indirects
                                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Spieler = Spieler Then
                                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).MinimaleReichweite > 1 And Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).MaximaleReichweite > 1 Then
                                                If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).MinimaleReichweite > 1 Then
                                                    Dim MaximalReichweite As Integer = -1
                                                    MaximalReichweite = Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).MaximaleReichweite
                                                    Dim D As Integer = Math.Abs(X - VerteidigerX) + Math.Abs(Y - VerteidigerY)
                                                    If D <= MaximalReichweite And D >= Einheit.MinimaleReichweite Then
                                                        AnzahlderEinheiten += 1
                                                    End If
                                                End If
                                            End If
                                        End If
                                    Case ObjektKO.Kampfboni.Vision
                                        If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Spieler = Spieler Then
                                            If Math.Abs(X - VerteidigerX) + Math.Abs(Y - VerteidigerY) <= Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).GetSicht(X, Y) Then
                                                AnzahlderEinheiten += 1
                                            End If
                                        End If
                                    Case ObjektKO.Kampfboni.EnemyAttack
                                        If Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).Spieler).Team <> Team Then
                                            'Das ist ein Feind
                                            If Objektverwalter.Spielfeld.Einheiten(X, Y, Schlacht).IsInFirerange(Einheit) = True Then
                                                AnzahlderEinheiten += 1
                                            End If
                                        End If
                                End Select
                            End If
                        End If
                    Next
                Next
                'Der Bonus wird addiert
                Offensive += AnzahlderEinheiten * KOS(0).StaerkebonusproEinheit
            End If
        End If
        'Manche Truppen erhalten einen Zusatzboost
        If VerteidigerX >= 0 And VerteidigerY >= 0 Then
            If IsNothing(Objektverwalter.Spielfeld.Einheiten(VerteidigerX, VerteidigerY, Schlacht)) = False Then
                If Objektverwalter.Spielfeld.Einheiten(VerteidigerX, VerteidigerY, Schlacht).MaximaleReichweite > 1 Then
                    Offensive += KOS(0).Zusatzoffensive.Y
                Else
                    Offensive += KOS(0).Zusatzoffensive.X
                End If
            End If
        End If
        'Der Bergbonus von Truppen wird addiert
        If KOS(0).Bergbonus.X <> 0 Then
            Dim Kreis1(,) As Integer = Kreisfunktion(KOS(0).Bergbonus.Y)
            For X = -KOS(0).Bergbonus.Y To KOS(0).Bergbonus.Y
                For Y = -KOS(0).Bergbonus.Y To KOS(0).Bergbonus.Y
                    If Kreis1(X + KOS(0).Bergbonus.Y, Y + KOS(0).Bergbonus.Y) >= 0 Then
                        Dim X1 As Integer = X + AngreiferX
                        Dim Y1 As Integer = Y + AngreiferY
                        If Objektverwalter.Spielfeld.OnMap(X1, Y1) Then
                            If Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlacht).getID = "BERG" Or Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlacht).getID = "GIPFEL" Or Objektverwalter.Spielfeld.Landschaften(X1, Y1, Schlacht).getID = "FELSEN" Then
                                Offensive += KOS(0).Bergbonus.X
                                GoTo BergGefunden
                            End If
                        End If
                    End If
                Next
            Next
BergGefunden:
        End If
        'Falls der KO auf dieser Landschaft einen Bonus erhaelt
        If Not Landschaft Is Nothing Then
            Dim Stelle As Integer = Array.IndexOf(KOS(0).LandschaftsUntergrund, Landschaft.getID)
            If Stelle >= 0 Then
                Offensive += KOS(0).LandschaftsStaerke
            Else
                If Not Einheit.IsFlyingUnit Then
                    Stelle = Array.IndexOf(KOS(0).LandschaftsUntergrund, "Deckung")
                    If Stelle >= 0 Then
                        Dim Deckung As Integer = GetDeffensivSterne(Deffender, Landschaft)
                        Offensive += KOS(0).LandschaftsStaerke * Deckung
                    End If
                End If
            End If
        End If
        'Der Wetterbonus wird addiert
        If KOS(0).Wetter = Objektverwalter.Spielfeld.Regeln.Wetter Then
            Offensive += KOS(0).Wetterbouns
        End If
        'Der Geldstaerkebonus wird addiert
        If KOS(0).Geldstaerke > 0 Then
            Dim Staerke As Integer = Math.DivRem(Fonds, KOS(0).Geldstaerke, 0)
            Offensive += Staerke * 10
        End If
        Offensive += KOS(0).Synergie

        'Falls der KO Vorteile oder Nachteile gegenueber Gruppen Angriffen hat. bekommt er diese Staerke
        Dim Kreis As Integer(,) = Kreisfunktion(ObjektKO.Radius)
        Dim ZahlderFeinde As Integer = 0
        'Wir finden die Position der Einheit heraus.
        Dim Position As Point = New Point(Einheit.X, Einheit.Y)
        If Einheit.X >= 0 Then
            If Objektverwalter.Spielfeld.Einheiten(Einheit.X, Einheit.Y, Schlacht) Is Nothing Then
                If Objektverwalter.Spielfeld.Laufen Is Nothing Then
                    'Darf nicht vorkommen kommt aber vor
                    If Not Objektverwalter.Spielfeld.CurrentAI Is Nothing Then
                        Position = Objektverwalter.Spielfeld.CurrentAI.GetEinheitenZiel
                    End If
                Else
                    Position = Objektverwalter.Spielfeld.Laufen.Position
                End If
            End If
            'Wir gehen alle Felder des Kreises durch
            For X = -ObjektKO.Radius To Kreis.GetLength(0) - ObjektKO.Radius - 1
                For Y = -ObjektKO.Radius To Kreis.GetLength(0) - ObjektKO.Radius - 1
                    If Kreis(ObjektKO.Radius + X, ObjektKO.Radius + Y) > 0 Then
                        If Objektverwalter.Spielfeld.OnMap(Position.X + X, Position.Y + Y) Then
                            'Ist auf diesem Feld eine einheit?
                            If Not Objektverwalter.Spielfeld.Einheiten(Position.X + X, Position.Y + Y, Schlacht) Is Nothing Then
                                'Ja! Ist sie ein Feind?
                                If Not Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).Team = Objektverwalter.Spielfeld.Spieler(Objektverwalter.Spielfeld.Einheiten(Position.X + X, Position.Y + Y, Schlacht).Spieler).Team Then
                                    'Das sind Feinde. Wie Praktisch dann zaehlen wir einen Feind dazu
                                    ZahlderFeinde += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        End If
        'So jetzt kennen wir die Zahl der Feinde.
        'wenn es mehr als X Einheiten sind wird die Einheit um Y staerker.=)
        If Einheit.Spieler > 0 Then
            If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).GruppenBoost(0).X < ZahlderFeinde Then
                Offensive += Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).GruppenBoost(0).Y
            End If
            'Wenn es weniger als X Einheiten sind wird sie um Y Staerker.=)
            If Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).GruppenBoost(1).X > ZahlderFeinde Then
                Offensive += Objektverwalter.Spielfeld.Spieler(Einheit.Spieler).KOS(0).GruppenBoost(1).Y
            End If
        End If
        'So falls unsere Einnahmen und Fonds verschieden sind kann es sein das wir besser bzw. schlechter kaempfen.
        If KOS(0).ATKundKostensteigererfuerFonds.X <> 0 Then
            Dim Einnahmen As Integer = Einkommen()
            If Einnahmen > Fonds Then
                Dim EinnahmenProzent As Integer = 0.1# * Einnahmen
                Offensive -= Math.DivRem(Einnahmen - Fonds, EinnahmenProzent, 0) * KOS(0).ATKundKostensteigererfuerFonds.X
            ElseIf Einnahmen < Fonds Then
                Dim EinnahmenProzent As Integer = 0.1# * Einnahmen
                Offensive += Math.DivRem(Fonds - Einnahmen, EinnahmenProzent, 0) * KOS(0).ATKundKostensteigererfuerFonds.X
            End If
        End If
        'Manche KOs sind umso schwaecher umso weniger TP ihre Truppen haben
        Offensive -= KOS(0).ZusaetlicheKampfschwaecheproTP * (10 - Einheit.getKP)
        'Wir sind staerker wenn wir eine bestimmte Landschaft angreifen.
        If VerteidigerX >= 0 And VerteidigerY >= 0 Then
            If FindElement(KOS(0).AufLandschaftsUntergrund, Objektverwalter.Spielfeld.Landschaften(VerteidigerX, VerteidigerY, Schlacht).getID) >= 0 Then
                Offensive += KOS(0).AufLandschaftsStaerke
            End If
            If AngreiferLeben > VerteidigerLeben Then
                Offensive += KOS(0).ATKHochfuerSchwacheGegner
            End If
        End If
        'Umso mehr Deckung der Gegner hat umso staerker sind wir. Tschuess Kat.
        If Objektverwalter.Spielfeld.OnMap(VerteidigerX, VerteidigerY) = True Then
            Offensive += KOS(0).FeuerstaerkeproFeindlicherDeckung * Objektverwalter.Spielfeld.Landschaften(VerteidigerX, VerteidigerY, Schlacht).Deckung
        End If

        Offensive = (Offensive - 100) * KOS(0).GetKOZoneBoost(Einheit) + 100

        Select Case DataSettings.CommanderWarsGameModus
            Case CommanderWarsGameModi.AdvanceWarsDC
                If Not KOS(0).Wetterimmunitaet.Contains(Objektverwalter.Spielfeld.Regeln.Wetter) Then
                    'Oh Sandsturm ist in DC\ DoR verdammt heftig
                    If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Sandsturm Then
                        Offensive -= 30
                    End If
                End If
            Case CommanderWarsGameModi.CommanderWars2
                If Not KOS(0).Wetterimmunitaet.Contains(Objektverwalter.Spielfeld.Regeln.Wetter) Then
                    'Oh Sandsturm ist in DC\ DoR verdammt heftig
                    If Objektverwalter.Spielfeld.Regeln.Wetter = ObjektSpielfeld.Wetterarten.Sandsturm Then
                        If Einheit.Bewegungsart.ToLower <> "wuestenketten" Then
                            Offensive -= 20
                        End If
                    End If
                End If
        End Select

        'Je nach Stufe wird die Einheit staerker
        Select Case Einheit.EinheitenStufe
            Case ObjektEinheit.Stufe.Leutnant
                Offensive += 5
            Case ObjektEinheit.Stufe.Offizier
                Offensive += 10
            Case ObjektEinheit.Stufe.General
                Offensive += 15
            Case ObjektEinheit.Stufe.Veteran
                Offensive += 20
            Case ObjektEinheit.Stufe.KO
                Offensive += 20
            Case Else
                Offensive += 0
        End Select
        'Der eigene Offensive Boost wird addiert
        Offensive += Einheit.ATKDEFBoost.X
        Offensive += GetGebaeude(ObjektSpieler.Gebaeudesuche.Sendetuerme) * KOS(0).SendeTurmStaerke.X
        'Es koennte passieren das die Offensie null wird das sollte nicht passieren.
        If Offensive < 0 Then
            Offensive = 0
        End If
        Return Offensive
    End Function
    Public Function GetDeffensivSterne(ByVal Verteidiger As ObjektEinheit, ByVal Landschaft As ObjektLandschaft)
        If Verteidiger IsNot Nothing Then
            If Verteidiger.IsFlyingUnit Then
                Return 0
            End If
        End If
        Dim Deckung As Integer = Landschaft.Deckung
        If KOS(0).DeckungsAenderung > 0 And KOS(0).DeckungsAenderung <> 1 Then
            Deckung *= KOS(0).DeckungsAenderung * KOS(0).GetKOZoneBoost(Landschaft.KooX, Landschaft.KooY)
        End If
        If Not Verteidiger Is Nothing Then
            Dim S As ObjektSpieler = Verteidiger.GetSpieler
            If S.KOS(0).DeckungsAenderung < 0 Then
                Deckung += Verteidiger.GetSpieler.KOS(0).DeckungsAenderung * S.KOS(0).GetKOZoneBoost(Verteidiger)
                If Deckung < 0 Then
                    Deckung = 0
                End If
            End If
        End If
        Return Deckung
    End Function
    Public Function Teurungsrate(ByVal Einheit As ObjektEinheit, ByVal X As Integer, ByVal Y As Integer) As Single
        Return Teurungsrate(Einheit.EinheitenID, X, Y)
    End Function
    Public Function Teurungsrate(ByVal EinheitenID As String, ByVal X As Integer, ByVal Y As Integer) As Single
        Dim Z As Single = 1
        Z = 1 - (1 - KOS(0).Teurungsrate) * KOS(0).GetKOZoneBoost(X, Y) - GetGebaeude(ObjektSpieler.Gebaeudesuche.Minen) * KOS(0).Minenstaerke * KOS(0).GetKOZoneBoost(X, Y)

        If KOS(0).ATKundKostensteigererfuerFonds.Y <> 0 Then
            Dim Einnahmen As Integer = Einkommen()
            If Einnahmen > Fonds Then
                Dim EinnahmenProzent As Integer = 0.1# * Einnahmen
                Z -= Math.DivRem(Einnahmen - Fonds, EinnahmenProzent, 0) * KOS(0).ATKundKostensteigererfuerFonds.Y / 100 * KOS(0).GetKOZoneBoost(X, Y)
            ElseIf Einnahmen < Fonds Then
                Dim EinnahmenProzent As Integer = 0.1# * Einnahmen
                Z += Math.DivRem(Fonds - Einnahmen, EinnahmenProzent, 0) * KOS(0).ATKundKostensteigererfuerFonds.Y / 100 * KOS(0).GetKOZoneBoost(X, Y)
            End If
        End If
        For I = 0 To KOS(0).BonusEinheiten.Length - 1
            If KOS(0).BonusEinheiten(I).ID = EinheitenID Then
                Z += KOS(0).BonusEinheiten(I).Wert * KOS(0).GetKOZoneBoost(X, Y)
            End If
        Next
        If Z < 0.2# Then
            Z = 0.2#
        End If
        Return Z
    End Function

    Public Function CanProduceUnit(ByVal Unit As ObjektEinheit) As Boolean
        Return CanProduceUnit(Unit.EinheitenID)
    End Function
    Public Function CanProduceUnit(ByVal UnitID As String) As Boolean
        If Bauliste.GetWert(UnitID) > 0 Then
            Return True
        Else
            Return False
        End If
    End Function
    Public Sub SpielerFrameRundenEnde()
        'Tja bloed gelaufen wir verlieren unser restliches Geld
        If VeraenderteWerte.KeineFondsamEnde = True Then
            Fond = 0
        End If
        VeraenderteWerte.Reset()
        KOS(0).TagEnde()
    End Sub
    Public Sub SpielerFrameRundenAnfang()
        KOS(0).KOFrame()
        KOS(0).Synergie = 0
        If Not KOS(1) Is Nothing Then KOS(1).Synergie = 0
        'Wir machen die Sache mit dem kuenstlichen Kriegsnebel
        EraseKriegsnebeldurchGabe()

    End Sub
    ''' <summary>
    ''' Berechnet die momementanen reperatur Kosten aller Truppen.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetRepairCosts() As Integer
        Dim Schlachten As Integer = 0
        Dim Fonds As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then Schlachten = 1
        For I = 0 To Schlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not E Is Nothing Then
                            If Not G Is Nothing Then
                                If E.Spieler = Spieler Then
                                    If IsReperaturGebaeude(G.GetSpieler) Then
                                        If G.GetBaulisteThisPlayer.Contains(E.EinheitenID) Then
                                            Fonds += GetRepairCosts(E)
                                        Else
                                            If TypeOf G Is GebaeudeStadt Then
                                                If ObjektLadeklasse.GetBauliste("BASIS").Contains(E.EinheitenID) Then
                                                    Fonds += GetRepairCosts(E)
                                                End If
                                            End If
                                        End If
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Fonds
    End Function
    ''' <summary>
    ''' Die Reperaturkosten fuer diese Runde!
    ''' </summary>
    ''' <param name="E"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetRepairCosts(ByVal E As ObjektEinheit) As Integer
        Dim Heilung As Integer = 10 - E.getKP
        Dim EinTPKosten As Integer = E.Kosten * Teurungsrate(E, E.X, E.Y) / 10
        Dim Gesamtkosten As Integer = 0
        For I = 1 To Heilung
            If I <= KOS(0).GebaeudeHeilung Then
                Gesamtkosten += EinTPKosten
            Else
                Exit For
            End If
        Next
        Return Gesamtkosten
    End Function
    ''' <summary>
    ''' Gibt an wie viele Gegner dieser Spieler hat.:)
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CountEnemies() As Integer
        Dim Enemies As Integer = 0
        For I = 1 To Objektverwalter.Spielfeld.Spieler.Length - 1
            If Objektverwalter.Spielfeld.Spieler(I).Team <> Team Then
                Enemies += 1
            End If
        Next
        Return Enemies
    End Function
    ''' <summary>
    ''' Hebt Kriegsnebel, welcher durch Gaben erschaffen wurde auf.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub EraseKriegsnebeldurchGabe()
        Dim NeuNebel As Nebelarten = Objektverwalter.Spielfeld.Regeln.Nebel
        Dim NebelBleibt As Boolean = False
        If KOS(0).KriegsnebelErstellung.Y > 0 Then
            KOS(0).KriegsnebelErstellung.Y -= 1
            If KOS(0).KriegsnebelErstellung.Y <= 0 Then
                KOS(0).KriegsnebelErstellung.Y = 0
                For Each MitSpieler In Objektverwalter.Spielfeld.Spieler
                    For Each KO In MitSpieler.KOS
                        If Not KO Is Nothing Then
                            If KO.KriegsnebelErstellung.Y > 0 Then
                                NebelBleibt = True
                            Else
                                If KO.KriegsnebelErstellung.X <> NeuNebel Then
                                    NeuNebel = KO.KriegsnebelErstellung.X
                                End If
                            End If
                        End If
                    Next
                Next
            End If
        End If
        If Not KOS(1) Is Nothing Then
            If KOS(1).KriegsnebelErstellung.Y > 0 Then
                KOS(1).KriegsnebelErstellung.Y -= 1
                If KOS(1).KriegsnebelErstellung.Y <= 0 Then
                    KOS(1).KriegsnebelErstellung.Y = 0
                    For Each MitSpieler In Objektverwalter.Spielfeld.Spieler
                        For Each KO In MitSpieler.KOS
                            If Not KO Is Nothing Then
                                If KO.KriegsnebelErstellung.Y > 0 Then
                                    NebelBleibt = True
                                Else
                                    If KO.KriegsnebelErstellung.X <> NeuNebel Then
                                        NeuNebel = KO.KriegsnebelErstellung.X
                                    End If
                                End If
                            End If
                        Next
                    Next
                End If
            End If
        End If
        If NebelBleibt = False Then
            Objektverwalter.Spielfeld.Regeln.Nebel = NeuNebel
        End If
        Objektverwalter.Spielfeld.Sichterstellen()
    End Sub
    ''' <summary>
    ''' So bekommt der Spieler fuer alle seine Gebaeude Geld.
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub EarnMoney()
        If VeraenderteWerte.KeineEinnahmen = False Then
            Dim Einnahmen As Integer = Einkommen()
            'Manche KOs muessen Steuern zahlen oder bekommen Geld aus dem Staatshaushalt. oder so aehnlich.
            Einnahmen += Einnahmen * KOS(0).MehrEinkommen
            AddFonds(Einnahmen)
        End If
    End Sub
    ''' <summary>
    ''' Gibt zurueck wie viel man einnimmt
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Einkommen() As Integer
        Dim Einnahmen As Integer = 0
        If VeraenderteWerte.GeldproBesetzungszahl = 0 Then
            Einnahmen = GetGebaeude(Gebaeudesuche.Fonds) * FondsproStadt
        Else
            Dim Fonds As Integer = 0
            Dim AnzahlSchlachten As Integer = 0
            If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then AnzahlSchlachten = 1
            For I = 0 To AnzahlSchlachten
                For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                    For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                        If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                            If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude Is Nothing Then
                                If Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude.Spieler = Spieler Then
                                    If Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude.getFonds = True Then
                                        Dim Senkung As Integer = ObjektGebaeude.Besetzungszahl - Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude.Besetzung
                                        Senkung = FondsproStadt * Senkung * VeraenderteWerte.GeldproBesetzungszahl
                                        Einnahmen += FondsproStadt + Senkung
                                    End If
                                End If
                            End If
                        End If
                    Next
                Next
            Next
        End If
        Einnahmen += GetGebaeude(Gebaeudesuche.Fonds) * KOS(0).BonusGeldproGebaeude
        Einnahmen -= Einnahmen * VeraenderteWerte.Einkommensveraenderung
        Return Einnahmen
    End Function
    ''' <summary>
    ''' Berechnet die Zahl der Einheitem
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CountUnits() As Integer
        Dim Schlachten As Integer = 0
        Dim Truppenzahl As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then Schlachten = 1
        For I = 0 To Schlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Spieler Then
                                Truppenzahl += 1
                                For Each ET In E.Ladung
                                    If ET IsNot Nothing Then
                                        Truppenzahl += 1
                                    End If
                                Next
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Truppenzahl
    End Function
    ''' <summary>
    ''' Berechnet die Zahl der Gebaeude inklusive Minigeschuetze usw.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CountBuildings() As Integer
        Dim Schlachten As Integer = 0
        Dim Buildings As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then Schlachten = 1
        For I = 0 To Schlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.Spieler = Spieler Then
                                If Not G.GetRealGebaeudeID = "VERWEIS" Then
                                    Buildings += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Buildings
    End Function
    ''' <summary>
    ''' Berechnet wie stark der Spieler ist.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CalculateSpielerStaerke() As Integer
        Dim Schlachten As Integer = 0
        Dim SpielerStaerke As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then Schlachten = 1
        For I = 0 To Schlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim E As ObjektEinheit = Objektverwalter.Spielfeld.Einheiten(X, Y, I)
                        If Not E Is Nothing Then
                            If E.Spieler = Spieler Then
                                SpielerStaerke += E.GetEinheitenWert
                            End If
                        End If
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If G.GetRealGebaeudeID <> "VERWEIS" Then
                                Dim GebaeudeWert As Integer = ObjektLadeklasse.GetGebaeudeKosten(G.GebaeudeID, G.Spieler)
                                If GebaeudeWert < 0 Then GebaeudeWert = 0
                                If GebaeudeWert > 0 Then
                                    If G.GetMaxLeben > 0 Then
                                        SpielerStaerke += GebaeudeWert * (G.GetKP(0, 0, True) / G.GetMaxLeben)
                                    Else
                                        SpielerStaerke += GebaeudeWert
                                    End If
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Dim BuildingProductions As Integer = CountBuildingProductions(-1)
        If BuildingProductions > 0 Then
            SpielerStaerke += Einkommen() * CountBuildingProductions(Spieler) / BuildingProductions * 5
        Else
            SpielerStaerke += Einkommen()
        End If
        Return SpielerStaerke
    End Function
    ''' <summary>
    ''' Zaehlt die Produktions Gebaeude 
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function CountBuildingProductions(ByVal FuerSpieler As Integer) As Integer
        Dim Schlachten As Integer = 0
        Dim Buildings As Integer = 0
        If Objektverwalter.Spielfeld.Regeln.Luftschlacht = True Then Schlachten = 1
        For I = 0 To Schlachten
            For X = 0 To Objektverwalter.Spielfeld.Breite - 1
                For Y = 0 To Objektverwalter.Spielfeld.Hoehe - 1
                    If Not Objektverwalter.Spielfeld.Landschaften(X, Y, I).Hidden Then
                        Dim G As ObjektGebaeude = Objektverwalter.Spielfeld.Landschaften(X, Y, I).Gebaeude
                        If Not G Is Nothing Then
                            If FuerSpieler > 0 Then
                                If G.Spieler = Spieler Then
                                    If Not G.GetRealGebaeudeID = "VERWEIS" Then
                                        If G.GetBaulisteThisPlayer.Length > 0 Then
                                            Buildings += 1
                                        End If
                                    End If
                                End If
                            ElseIf Not G.GetRealGebaeudeID = "VERWEIS" Then
                                If G.GetBauliste.Length > 0 Then
                                    Buildings += 1
                                End If
                            End If
                        End If
                    End If
                Next
            Next
        Next
        Return Buildings
    End Function
    ''' <summary>
    ''' Diese Werte wurden durch eine feindliche Gabe veraendert und werden am Ende der Runde Resetet
    ''' </summary>
    ''' <remarks></remarks>
    Structure WertedurchGabegeaendert
        Const Version As Byte = 0
        Public Sub New(ByVal N As Integer)
            Reset()
        End Sub
        ''' <summary>
        ''' Umso viel werden die Bewegungskosten pro Feld geaendert
        ''' </summary>
        ''' <remarks></remarks>
        Public Bewegungskosten As Integer
        ''' <summary>
        ''' umso viel werden Deckungsboni abgeschwaecht bzw. verstaerkt 1=keine Veraenderung
        ''' </summary>
        ''' <remarks></remarks>
        Public TerrainVeraender As Single
        ''' <summary>
        ''' Der Spieler kann keine Truppen bauen
        ''' </summary>
        ''' <remarks></remarks>
        Public KeinBau As Boolean
        ''' <summary>
        ''' Umso viel wird das Einkommen veraendert
        ''' </summary>
        ''' <remarks></remarks>
        Public Einkommensveraenderung As Single
        ''' <summary>
        ''' Fuer jeden Besetzungszahl kleiner 0 weniger Geld fuer diese Stadt.
        ''' </summary>
        ''' <remarks></remarks>
        Public GeldproBesetzungszahl As Single
        ''' <summary>
        ''' Mit so viel TP werden Einheiten gebaut.
        ''' </summary>
        ''' <remarks></remarks>
        Public TPBauEinheiten As Integer
        ''' <summary>
        ''' Wenn True hat man am Runden ende keine Fonds mehr.
        ''' </summary>
        ''' <remarks></remarks>
        Public KeineFondsamEnde As Boolean
        ''' <summary>
        ''' Um so viel Teurer ist eine Reperatur.
        ''' </summary>
        ''' <remarks></remarks>
        Public Reperaturkosten As Single
        ''' <summary>
        ''' Gibt an ob man Angreifen kann.
        ''' </summary>
        ''' <remarks></remarks>
        Public KeinAngriffausserINF As Boolean
        ''' <summary>
        ''' wenn groesser 0 haben alle Einheiten die Sichtweite unten.
        ''' </summary>
        ''' <remarks></remarks>
        Public SichtradiusVeraenderung As Integer
        ''' <summary>
        ''' Wenn False kann man keine Gabe einsetzen
        ''' </summary>
        ''' <remarks></remarks>
        Public Gabeeinsatz As Boolean
        ''' <summary>
        ''' wenn -999 dann Default ansonsten Aenderung von Glueck auf X und Pech auf Y
        ''' </summary>
        ''' <remarks></remarks>
        Public Gluecksaenderung As Point
        ''' <summary>
        ''' Der Spieler kann keine eigenen TP sehen
        ''' </summary>
        ''' <remarks></remarks>
        Public EigeneTPVersteckt As Boolean
        ''' <summary>
        ''' Der Spieler kann keine feindlichen TP sehen
        ''' </summary>
        ''' <remarks></remarks>
        Public FeindlicheTPVersteckt As Boolean
        ''' <summary>
        ''' X=1 Ja und X=0 Nein und Y=fuer N-Tage noch
        ''' </summary>
        ''' <remarks></remarks>
        Public KeineVersorgung As Point
        ''' <summary>
        ''' Diese Felder mit X,Y haben die Bewegungskosten Z
        ''' </summary>
        ''' <remarks></remarks>
        Public VeraenderteBewegungsFelder As Stack(Of Vector3)
        ''' <summary>
        ''' Wenn True laedt sich die Gabeleiste nicht auf.
        ''' </summary>
        ''' <remarks></remarks>
        Public KeinGabeFortschritt As Boolean
        ''' <summary>
        ''' Wenn True erhaelt der Spieler keine Information ueber die Fonds der Spieler
        ''' </summary>
        ''' <remarks></remarks>
        Public KeineFondsInfos As Boolean
        ''' <summary>
        ''' Wenn True erhaelt der Spieler keine Information ueber die Einnahmen der Spieler
        ''' </summary>
        ''' <remarks></remarks>
        Public KeineEinnahmenInfos As Boolean
        ''' <summary>
        ''' Wenn True erhalten wir kein Geld diese Runde
        ''' </summary>
        ''' <remarks></remarks>
        Public KeineEinnahmen As Boolean
        Public Sub Reset()
            Bewegungskosten = 0
            TerrainVeraender = 1
            KeinBau = False
            Einkommensveraenderung = 0
            GeldproBesetzungszahl = 0
            TPBauEinheiten = 10
            KeineFondsamEnde = False
            Reperaturkosten = 1
            KeinAngriffausserINF = False
            SichtradiusVeraenderung = -1
            Gabeeinsatz = True
            Gluecksaenderung = New Point(-999, -999)
            EigeneTPVersteckt = False
            FeindlicheTPVersteckt = False
            Dim X As Integer = KeineVersorgung.Y - 1
            If X <= 0 Then
                KeineVersorgung = New Point(0, 0)
            Else
                KeineVersorgung = New Point(1, X)
            End If
            VeraenderteBewegungsFelder = New Stack(Of Vector3)
            KeinGabeFortschritt = False
            KeineFondsInfos = False
            KeineEinnahmenInfos = False
            KeineEinnahmen = False
        End Sub
        Public Sub Write(ByRef StrW As Filestream)
            StrW.WriteByte(Version)
            Dim B(3) As Byte
            B = IntToBytes(Bewegungskosten)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = SingletoBytes(TerrainVeraender)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(KeinBau)
            B = SingletoBytes(Einkommensveraenderung)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = SingletoBytes(GeldproBesetzungszahl)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(TPBauEinheiten)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(KeineFondsamEnde)
            B = SingletoBytes(Reperaturkosten)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(KeinAngriffausserINF)
            B = IntToBytes(SichtradiusVeraenderung)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(Gabeeinsatz)
            B = IntToBytes(Gluecksaenderung.X)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(Gluecksaenderung.Y)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            StrW.WriteByte(EigeneTPVersteckt)
            StrW.WriteByte(FeindlicheTPVersteckt)
            B = IntToBytes(KeineVersorgung.X)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            B = IntToBytes(KeineVersorgung.Y)
            For I = 0 To B.Length - 1
                StrW.WriteByte(B(I))
            Next
            Dim Vec3s() As Vector3 = VeraenderteBewegungsFelder.ToArray
            WriteVec3Array(StrW, Vec3s)
            StrW.WriteByte(KeinGabeFortschritt)
            StrW.WriteByte(KeineFondsInfos)
            StrW.WriteByte(KeineEinnahmenInfos)
            StrW.WriteByte(KeineEinnahmen)
        End Sub
        Public Sub Read(ByRef StrR As Filestream)
            Dim V As Byte = StrR.ReadByte 'Version
            Dim B(3) As Byte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            Bewegungskosten = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            TerrainVeraender = BytesToSingle(B)
            KeinBau = StrR.ReadByte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            Einkommensveraenderung = BytesToSingle(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            GeldproBesetzungszahl = BytesToSingle(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            TPBauEinheiten = BytesToInt(B)
            KeineFondsamEnde = StrR.ReadByte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            Reperaturkosten = BytesToSingle(B)
            KeinAngriffausserINF = StrR.ReadByte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            SichtradiusVeraenderung = BytesToInt(B)
            Gabeeinsatz = StrR.ReadByte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            Gluecksaenderung.X = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            Gluecksaenderung.Y = BytesToInt(B)
            EigeneTPVersteckt = StrR.ReadByte
            FeindlicheTPVersteckt = StrR.ReadByte
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            KeineVersorgung.X = BytesToInt(B)
            For I = 0 To B.Length - 1
                B(I) = StrR.ReadByte()
            Next
            KeineVersorgung.Y = BytesToInt(B)
            Dim Vec3s() As Vector3 = ReadVec3Array(StrR)
            VeraenderteBewegungsFelder.Clear()
            For I = 0 To Vec3s.Length - 1
                VeraenderteBewegungsFelder.Push(Vec3s(I))
            Next
            KeinGabeFortschritt = StrR.ReadByte
            KeineFondsInfos = StrR.ReadByte
            KeineEinnahmenInfos = StrR.ReadByte
            KeineEinnahmen = StrR.ReadByte
        End Sub
    End Structure
    Public Function GetGlueckPech(ByVal X As Integer, ByVal Y As Integer) As Point
        Dim GlueckPech As Point
        If VeraenderteWerte.Gluecksaenderung.X = -999 Then
            GlueckPech.X = KOS(0).Glueck * KOS(0).GetKOZoneBoost(X, Y)
            GlueckPech.Y = KOS(0).Pech * KOS(0).GetKOZoneBoost(X, Y)
        Else
            GlueckPech.X = VeraenderteWerte.Gluecksaenderung.X
            GlueckPech.Y = VeraenderteWerte.Gluecksaenderung.Y
        End If
        If Objektverwalter.Spielfeld.Regeln.NoLuck Then
            Dim LuckRange As Integer = (GlueckPech.X + GlueckPech.Y) / 2
            Return New Point(LuckRange, LuckRange)
        Else
            Return GlueckPech
        End If

    End Function
    Public Function GetArmyNumber() As Integer
        Dim Army As Integer = [Enum].Parse(Commander_Wars.Armeen.GE.GetType, GetArmyOutFit(Armeen))
        If Army > Commander_Wars.Armeen.BG Then Army -= 1
        If Army < 0 Then
            Return 0
        Else
            Return Army
        End If
    End Function
    ''' <summary>
    ''' Ueberprueft ob mit diesem Gebaeude repariert werden kann.
    ''' </summary>
    ''' <param name="GebaeudeSpieler">Der Spieler dem das Gebaeude gehoert.</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function IsReperaturGebaeude(ByVal GebaeudeSpieler As ObjektSpieler) As Boolean
        Dim R As ObjektKO.ReperaturGebaeude = KOS(0).RepairON
        Select Case DataSettings.CommanderWarsGameModus
            Case CommanderWarsGameModi.AdvanceWarsDC, CommanderWarsGameModi.CommanderWars2
                If R = ObjektKO.ReperaturGebaeude.Own Then
                    R = ObjektKO.ReperaturGebaeude.Allied
                ElseIf R = ObjektKO.ReperaturGebaeude.OwnAndEnemy Then
                    R = ObjektKO.ReperaturGebaeude.AlliedAndEnemy
                ElseIf R = ObjektKO.ReperaturGebaeude.OwnAndEnemyAndNeutral Then
                    R = ObjektKO.ReperaturGebaeude.AlliedAndEnemyAndNeutral
                ElseIf R = ObjektKO.ReperaturGebaeude.OwnAndNeutral Then
                    R = ObjektKO.ReperaturGebaeude.AlliedAndNeutral
                End If
        End Select
        Select Case R
            Case ObjektKO.ReperaturGebaeude.OwnAndEnemyAndNeutral
                If GebaeudeSpieler.Spieler = Spieler Or GebaeudeSpieler.Team <> Team Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.OwnAndEnemy
                If GebaeudeSpieler.Spieler = Spieler Or GebaeudeSpieler.Team <> Team And GebaeudeSpieler.Spieler > 0 Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.OwnAndNeutral
                If GebaeudeSpieler.Spieler = Spieler Or GebaeudeSpieler.Spieler = 0 Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.Own
                If GebaeudeSpieler.Spieler = Spieler Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.Allied
                If GebaeudeSpieler.Team = Team Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.AlliedAndEnemy
                If GebaeudeSpieler.Team = Team Or GebaeudeSpieler.Spieler > 0 And GebaeudeSpieler.Team <> Team Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.AlliedAndNeutral
                If GebaeudeSpieler.Team = Team Or GebaeudeSpieler.Spieler = 0 Then
                    Return True
                Else
                    Return False
                End If
            Case ObjektKO.ReperaturGebaeude.AlliedAndEnemyAndNeutral
                Return True
        End Select
    End Function
    ''' <summary>
    ''' Gibt alle Einheiten dieses Spielers zurueck
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function GetUnits() As ObjektEinheit()
        Dim Truppen As ObjektEinheit() = {}
        For Each Unit In Objektverwalter.Spielfeld.Einheiten
            If Not Unit Is Nothing Then
                If Not Objektverwalter.Spielfeld.Landschaften(Unit.X, Unit.Y, Unit.GetMap).Hidden Then
                    If Unit.Spieler = Spieler Then
                        Array.Resize(Truppen, Truppen.Length + 1)
                        Truppen(Truppen.Length - 1) = Unit
                    End If
                End If
            End If
        Next
        Return Truppen
    End Function
    Public Sub AddExternGezogeneEinheit(ByVal ZielX As Integer, ByVal ZielY As Integer, ByVal Einheit As ObjektEinheit, ByVal Befehl As ExternGezogeneEinheit.Befehle, ByVal ZielID As String, ByVal NaechsterBefehl As ExternGezogeneEinheit.NaechsteBefehle)
        Array.Resize(ExternGezogeneEinheiten, ExternGezogeneEinheiten.Length + 1)
        ExternGezogeneEinheiten(ExternGezogeneEinheiten.Length - 1) = New ExternGezogeneEinheit(ZielX, ZielY, Einheit, Befehl, ZielID, NaechsterBefehl)
    End Sub
    Public Sub RemoveEinheit(ByVal E As ObjektEinheit)
        For I = 0 To ExternGezogeneEinheiten.Length - 1
            If E.Equals(ExternGezogeneEinheiten(I).Einheit) Then
                ExternGezogeneEinheiten(I) = ExternGezogeneEinheiten(ExternGezogeneEinheiten.Length - 1)
                Array.Resize(ExternGezogeneEinheiten, ExternGezogeneEinheiten.Length - 1)
                Exit For
            End If
        Next
    End Sub
    Public Sub RemoveEinheit(ByVal E As ObjektEinheit, ByVal Befehl As ExternGezogeneEinheit.Befehle)
        For I = 0 To ExternGezogeneEinheiten.Length - 1
            If ExternGezogeneEinheiten(I).Befehl = Befehl Then
                If E.Equals(ExternGezogeneEinheiten(I).Einheit) Then
                    ExternGezogeneEinheiten(I) = ExternGezogeneEinheiten(ExternGezogeneEinheiten.Length - 1)
                    Array.Resize(ExternGezogeneEinheiten, ExternGezogeneEinheiten.Length - 1)
                    Exit For
                End If
            End If
        Next
    End Sub
    Public Sub RemoveEinheit(ByVal Stelle As Integer)
        ExternGezogeneEinheiten(Stelle) = ExternGezogeneEinheiten(ExternGezogeneEinheiten.Length - 1)
        Array.Resize(ExternGezogeneEinheiten, ExternGezogeneEinheiten.Length - 1)
    End Sub

    Public Shared Function GetNeutralGebaeudeTexturID(ByVal GebaeudeID As String) As Integer
        For I = 0 To Objektverwalter.AlleGebaeude.Length - 1
            If Objektverwalter.AlleGebaeude(I).GebaeudeID = GebaeudeID Then
                Return I
            End If
        Next
        Return 0
    End Function
    Public Shared Function GetNeutralSpezialGebaeudeTexturID(ByVal GebaeudeID As String) As Integer
        Dim Spieler As ObjektSpieler = Objektverwalter.Spielfeld.Spieler(0)
        Dim Z As Integer = -1
        For I = 0 To Objektverwalter.AlleGebaeude.Length - 1
            If Objektverwalter.AlleGebaeude(I).GebaeudeID = GebaeudeID Then
                Return I
            End If
        Next
        Return 0
    End Function
#End Region

    ''' <summary>
    ''' Sollte nur von Spielfeld aufgerufen werden.
    ''' Extern gezogene Einheiten brauchen dann noch ein Update.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Clone() As Object Implements System.ICloneable.Clone
        Dim S As ObjektSpieler = MemberwiseClone()
        S.KOS = New ObjektKO() {ObjektLadeklasse.NewKO(KOS(0).KOID, Spieler), Nothing}
        If KOS(1) IsNot Nothing Then S.KOS(1) = ObjektLadeklasse.NewKO(KOS(1).KOID, Spieler)
        ReDim S.Sichtfelder(Sichtfelder.Length - 1)
        For I = 0 To Sichtfelder.Length - 1
            S.Sichtfelder(I) = New Vector4(Sichtfelder(I).X, Sichtfelder(I).Y, Sichtfelder(I).Z, Sichtfelder(I).W)
        Next
        ReDim S.ExternGezogeneEinheiten(ExternGezogeneEinheiten.Length - 1)
        For I = 0 To ExternGezogeneEinheiten.Length - 1
            S.ExternGezogeneEinheiten(I) = ExternGezogeneEinheiten(I).Clone
        Next
        If Bauliste IsNot Nothing Then
            S.Bauliste = Bauliste.Clone
        End If
        Return S
    End Function
End Class
